package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"gitee.com/thubcc/p2pgit/constant"
	"gitee.com/thubcc/p2pgit/gitpack"
	"gitee.com/thubcc/p2pgit/some"
	"gitee.com/thubcc/p2pgit/types"
	"gitee.com/thubcc/p2pgit/utils"
	"github.com/a4a881d4/gitcrawling/packext"
	"gopkg.in/src-d/go-git.v4/plumbing"
)

var (
	argNewPack = flag.String("n", "../temp", "New Pack Dir")
	argGitPack = flag.String("g", "../temp", "Git Pack Dir")
	argWrite   = flag.Bool("w", false, "Write")
)

var t = log.New(os.Stdout, "git:", 6)

func findFile() (r []string) {
	packext.DefaultFromDir(*argGitPack)
	for _, v := range packext.DefaultMap {
		r = append(r, strings.Replace(v, ".pack", ".idx", -1))
	}
	return
}

func write(gs types.SomeGeter) {
	var err error
	ps := types.NewRawer(some.Geter2Rawer(gs))
	err = ps.Open(true)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer ps.Close()
	var do = func(forTest string) (cerr error) {
		t.Println("Begin", forTest)
		cerr = gitpack.TravelGitPackFile(forTest, some.NewPackCB(&ps))
		if cerr != nil {
			t.Println("test", forTest, cerr)
		}
		t.Println("End", forTest)
		return
	}
	files := findFile()
	go func() {
		for {
			<-time.After(constant.SyncTimer)
			ps.Sync()
		}
	}()
	for _, fn := range files {
		err := do(fn)
		if err != nil {
			t.Println(fn, err)
		}
	}
}

func read(objs []types.Hash, gs types.SomeGeter) {
	var err error
	ps := types.NewRawer(some.Geter2Rawer(gs))
	err = ps.Open(true)
	if err != nil {
		fmt.Println(err)
		return
	}

	p := utils.NewProgress("Read:", len(objs))
	p.Every = 10000
	p.Init()
	defer p.End()
	for k, v := range objs {
		var obj []byte
		var typ plumbing.ObjectType
		obj, typ, err = types.ResolveObj(gs, types.HashSelect(v))
		if err != nil {
			t.Println("get", k, v)
			t.Println(err)
		}
		ghash := plumbing.ComputeHash(typ, obj)
		if types.Hash(ghash) != v {
			t.Println(k, v.String(), "!=", ghash.String())
		}
		p.Done()
	}
}

func main() {
	flag.Parse()

	if *argWrite {
		// gs := types.SomeGeter{
		// 	&classedpack.File{
		// 		C: &classify.BasicClassify{
		// 			Prefix: 0,
		// 			BitLen: 0,
		// 		},
		// 		Dir: *argNewPack,
		// 	},
		// }
		gs, err := some.GeterFromDir(*argNewPack)
		if err != nil {
			fmt.Println("get geters from", *argNewPack, err)
			return
		}
		write(gs)
		t.Println("write done")
	} else {
		gs, err := some.GeterFromDir(*argNewPack)
		if err != nil {
			fmt.Println("get geters from", *argNewPack, err)
			return
		}
		objs := some.Geter2Hashes(gs)
		t.Println("find done")
		read(objs, gs)
		t.Println("read done")
	}
}
